# bison yacc grammar language lexer+parser to use with packcc parser generator
%prefix "yacc"

%source{

#include <stdio.h>

static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" };

#define PCC_DEBUG(event, rule, level, pos, buffer, length) \
    fprintf(stdout, "%*s%s %s @%d [%.*s]\n", (int)(level * 2), "", dbg_str[event], rule, (int)pos, (int)length,  buffer); fflush(stdout)

    /* NOTE: To guarantee the output order, stderr, which can lead a race condition with stdout, is not used. */

}

file <- _ part1* _ "%%" _ part2 _ part3? _ !.

part1	<-  part1a  { fprintf(stderr,"part1 is->\"%s\"\n",$0); }

part1a	<- _ part1sub* _  { fprintf(stderr,"part1-sub is->\"%s\"\n",$0); }

part1sub	<- part1nterm
	/ part1token
	/ part1type
	/ part1left
	/ part1right
	/ part1nonassoc
	/ part1precedence
	/ part1start
	/ part1destructor
	/ part1printer
	/ part1defaultprec
	/ part1nodefaultprec
	/ part1perccode
	/ part1ccode { fprintf(stderr,"part1 code is->\"%s\"\n",$0); }
	/ part1define
	/ part1defines
	/ part1errorverbose
	/ part1expect
	/ part1expectrr
	/ part1fileprefix
	/ part1glrparser
	/ part1initialaction
	/ part1language
	/ part1nameprefix
	/ part1nolines
	/ part1nondeterministicparser
	/ part1output
	/ part1param
	/ part1pureparser
	/ part1require
	/ part1skeleton
	/ part1tokentable
	/ part1verbose
	/ part1yacc
	/ part1semic

#	/ (!"%%" .)*   { fprintf(stderr,"part1 rest is->\"%s\"\n",$0); }

part1nterm	<- "%nterm" sp+

part1token	<- "%token" sp+

part1type	<- "%type" sp+

part1left	<- "%left" sp+

part1right	<- "%right" sp+

part1nonassoc	<- "%nonassoc" sp+

part1precedence	<- "%precedence" sp+

part1start	<- "%start" sp+ part1startid sp+

part1startid	<- (ID / NT)+ { fprintf(stderr,"part1 start is->\"%s\"\n",$0); }

part1destructor	<- "%destructor" sp+

part1printer	<- "%printer" sp+

part1defaultprec	<- ("%default-prec" / "%default_prec") sp+

part1nodefaultprec	<- ("%no-default-prec" / "%no_default-prec" / "%no-default_prec" / "%no_default_prec") sp+

part1perccode	<- "%code" part1perccodeid* sp+

part1perccodeid	<- sp+ (ID / NT)+

part1define	<- "%define" sp+

part1defines	<- "%defines"

part1errorverbose	<- ("%error-verbose" / "%error_verbose")

part1expect	<- "%expect" sp+

part1expectrr	<- ("%expect-rr" / "%expect_rr") sp+

part1fileprefix	<- ("%file-prefix" / "%file_prefix") sp+

part1glrparser	<- ("%glr-parser" / "%glr_parser")

part1initialaction	<- ("%initial-action" / "%initial_action") sp+

part1language	<- "%language" sp+

part1nameprefix	<- ("%name-prefix" / "%name_prefix") sp+

part1nolines	<- ("%no-lines" / "%no_lines")

part1nondeterministicparser	<- ("%nondeterministic-parser" /  "%nondeterministic_parser")

part1output	<- "%output"

part1param 	<- "%param"

part1pureparser	<- ("%pure-parser" / "%pure_parser")

part1require	<- "%require" sp+

part1skeleton	<- "%skeleton" sp+

part1tokentable	<- ("%token-table" / "%token_table")

part1verbose	<- "%verbose"

part1yacc	<- "%yacc"

part1semic	<- ";"

part1ccode	<- cs (!es .)* es

part2	<- (part2a)* "%%"  { fprintf(stderr,"part2 is-\"%s\"\n",$0); }
	/ part2a*  { fprintf(stderr,"part2 is -no%%--\"%s\"\n",$0); }

part2a	<- (!pp .)* { fprintf(stderr,"part2a rest is -\"%s\"\n",$0); }

part3	<- any  { fprintf(stderr,"part3 is -\"%s\"\n",$0); }

cs	<-	"%{"

es	<-	"%}"

pp	<- "%%"

ecs	<-	'*/'

ID	<-	[A-Za-z_][_A-Za-z0-9]*

NT	<-	[A-Za-z._][_.A-Za-z0-9]*

any	<- (!endofline !"%%" .)*

sp	<-	[ \t]

WHITESPACE <-	(' '/'\t'/'\n'/'\r')

COMMENT <-	"//" (!endofline .)*

CCOMMENT <-	'/*' ( !ecs .)* '*/' / ("/*" "*" "/")  { fprintf(stderr,"c-comment is -\"%s\"\n",$0); }

_	<- (WHITESPACE / COMMENT / CCOMMENT / endofline)*

endofline	<-	( '\r\n' / '\n' / '\r' / '\n\r' )

%%

int main() {
    yacc_context_t *ctx=yacc_create(NULL);
    while (yacc_parse(ctx, NULL)){;}
    yacc_destroy(ctx);
    return 0;
}

